<template>
  <div>
    <el-button @click="startDrawing" :disabled="startButton" type="primary">开始绘制</el-button>
    <div id="map-container"></div>
  </div>
</template>
<script>
import { Map, View } from 'ol'
import { Tile as TileLayer } from 'ol/layer'
import { get } from 'ol/proj';
import { getWidth, getTopLeft } from 'ol/extent'
import { WMTS } from 'ol/source'
import WMTSTileGrid from 'ol/tilegrid/WMTS'
import { defaults as defaultControls} from 'ol/control';
import { GeoJSON } from 'ol/format';
import { Vector as VectorLayer } from 'ol/layer';
import { Vector as VectorSource } from 'ol/source';
import { Feature } from 'ol';
import Text from 'ol/style/Text';
import {Fill, Stroke, Style} from "ol/style";
import {LineString, Point} from "ol/geom";
import { getDistance } from 'ol/sphere';


export const projection = get("EPSG:4326");
const projectionExtent = projection.getExtent();
const size = getWidth(projectionExtent) / 256;
const resolutions = [];
for (let z = 0; z < 19; ++z) {
  resolutions[z] = size / Math.pow(2, z);
}

export default {
  data() {
    return {
      map:null,
      drawing: false,
      //是否禁用开始绘制按钮
      startButton:false,
      //存放当前经纬度集合
      currentCoordinates: [],
      // 存储虚线图层
      lineLayer: null,
      // 存放文本图层
      distanceLayer: null,
      // 存储虚线经纬度
      lineCoordinates:[],
    }
  },
  mounted(){
    this.initMap() // 加载矢量底图
  },
  methods:{
    initMap() {
      const KEY = '你申请的KEY'
      // 创建一个 distanceSource 用于存放所有的角度标注
      const distanceSource = new VectorSource();
      this.distanceLayer = new VectorLayer({
        source: distanceSource,
      });
      this.map = new Map({
        target: 'map-container',
        layers: [
          // 底图
          new TileLayer({
            source: new WMTS({
              url: `http://t{0-6}.tianditu.com/vec_c/wmts?tk=${KEY}`,
              layer: 'vec', // 矢量底图
              matrixSet: 'c', // c: 经纬度投影 w: 球面墨卡托投影
              style: "default",
              crossOrigin: 'anonymous', // 解决跨域问题 如无该需求可不添加
              format: "tiles", //请求的图层格式，这里指定为瓦片格式
              wrapX: true, // 允许地图在 X 方向重复（环绕）
              tileGrid: new WMTSTileGrid({
                origin: getTopLeft(projectionExtent),
                resolutions: resolutions,
                matrixIds: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15','16','17','18']
              })
            })
          }),
          // 标注
          new TileLayer({
            source: new WMTS({
              url: `http://t{0-6}.tianditu.com/cva_c/wmts?tk=${KEY}`,
              layer: 'cva', //矢量注记
              matrixSet: 'c',
              style: "default",
              crossOrigin: 'anonymous',
              format: "tiles",
              wrapX: true,
              tileGrid: new WMTSTileGrid({
                origin: getTopLeft(projectionExtent),
                resolutions: resolutions,
                matrixIds: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15','16','17','18','19']
              })
            })
          }),
          this.distanceLayer,
        ],
        view: new View({
          center: [120.430070,31.938140],
          projection: projection,
          zoom: 15,
          maxZoom: 19,
          minZoom: 1
        }),
        //加载控件到地图容器中
        controls: defaultControls({
          zoom: false,
          rotate: false,
          attribution: false
        })
      });
      //初始化地图点击事件
      this.initMapClickEvent();
    },

    //初始化地图点击事件
    initMapClickEvent() {
      let _that = this;
      // 添加点击事件监听
      this.map.on('click', (event) => {
        if (_that.drawing) {
          _that.addPoint(event.coordinate);
        }
      });

      // 添加鼠标移动事件
      this.map.on('pointermove', (event) => {
        if (_that.drawing) {
            //更新线的位置
          _that.updateLine(event.coordinate);
        }
      });
    },
    //添加点
    addPoint(coordinate) {
      //添加到当前线经纬度集合
      this.lineCoordinates.push(coordinate);
      //添加到当前点经纬度集合
      this.currentCoordinates.push(coordinate);
      //满足二个点自动停止
      if(this.currentCoordinates.length === 2) {
        const distance = this.calculateDistance(this.currentCoordinates[0],this.currentCoordinates[1]);
        this.addDistanceLabel(this.currentCoordinates[1],distance);
        this.endDrawing();
      }
    },

    //开始绘制
    startDrawing(){
      //激活绘画功能
      this.drawing = true;
      //禁用开始绘制按钮
      this.startButton = true;
    },

    //结束绘制
    endDrawing(){
      //禁用绘画功能
      this.drawing = false;
      //将当前点经纬度信息置空
      this.currentCoordinates = [];
      //将当前线经纬度信息置空
      this.lineCoordinates = [];
      //虚线图层重置
      this.lineLayer = null;
      //释放开始绘制按钮
      this.startButton = false;
    },

    updateLine(coordinate) {
      if (this.lineLayer) {
        // 更新现有线的最后一个坐标
        this.lineCoordinates[this.lineCoordinates.length - 1] = coordinate; // 修改最后一点
        const lineString = new LineString(this.lineCoordinates);
        this.lineLayer.getSource().getFeatures()[0].setGeometry(lineString);
      } else {
        this.lineCoordinates.push(coordinate);
        // 创建虚线图层
        this.lineLayer = new VectorLayer({
          source: new VectorSource({
            features: [new Feature(new LineString(this.lineCoordinates))],
          }),
          style: new Style({
            stroke: new Stroke({
              color: 'rgb(255,0,0)',
              width: 3,
            }),
          }),
        });
        this.map.addLayer(this.lineLayer);
      }
    },

    // 计算距离
    calculateDistance(start,end) {
      const length = getDistance(start, end);
      const distance = length.toFixed(2); // 保留两位小数
      return distance;
    },

    // 添加文本标注
    addDistanceLabel(coordinate, distance) {
      const distanceFeature = new Feature({
        geometry: new Point(coordinate),
        distance: `距离: ${distance}米`, // 文本内容
      });

      // 创建文本样式
      const textStyle = new Style({
        text: new Text({
          text: distanceFeature.get('distance'),
          font: '20px Calibri,sans-serif',
          fill: new Fill({ color: 'black' }),
          stroke: new Stroke({
            color: 'white',
            width: 2,
          }),
          offsetX: 0, // 偏移量，调整文本位置
          offsetY: 25,
        }),
      });

      // 设置特征样式
      distanceFeature.setStyle(textStyle);

      // 将新的特征添加到共享的图层的源中
      this.distanceLayer.getSource().addFeature(distanceFeature);

    }
  },
}
</script>
<style scoped>
#map-container {
  width: 100%;
  height: 100vh;
}
</style>
